﻿using System.ClientModel;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.AI;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Diagnostics;

namespace HB.AbpFundation.Samples;

public class SampleAppService : AbpFundationAppService, ISampleAppService
{
    public async IAsyncEnumerable<string> ChatAsync(ChatInput input)
    {
        IChatClient openaiClient =
   new OpenAI.Chat.ChatClient("deepseek-chat", new ApiKeyCredential("sk-e7a0e0fbeaa54443aeb12a9bee6e2321"), new OpenAI.OpenAIClientOptions()
   {
       Endpoint = new Uri("https://api.deepseek.com/v1"),

   })
   .AsIChatClient();
        var chatOptions = new ChatOptions
        {
            Tools = [AIFunctionFactory.Create(Tools.read_from_file),
                AIFunctionFactory.Create(Tools.write_to_file),
                AIFunctionFactory.Create(Tools.read_from_file),
                AIFunctionFactory.Create(Tools.list_file),
                AIFunctionFactory.Create(Tools.execute_command),
                AIFunctionFactory.Create(Tools.delete_file)],
            Temperature = 0,
            ToolMode = ChatToolMode.Auto,
            // ResponseFormat=ChatResponseFormat.Json,
            AllowMultipleToolCalls = true,

        };

        IChatClient client = new ChatClientBuilder(openaiClient)
            // .UseDistributedCache(cache)
            .UseFunctionInvocation()
            //.UseOpenTelemetry(sourceName: sourceName, configure: c => c.EnableSensitiveData = true)
            .Build();
        List<ChatMessage> historyMessage = new List<ChatMessage>();
        historyMessage.Add(new ChatMessage(ChatRole.System, input.System));
        historyMessage.Add(new ChatMessage(ChatRole.User, input.Message));
        string assistantContent = string.Empty;
        await foreach (var message in client.GetStreamingResponseAsync(historyMessage, chatOptions))
        {
            // Console.Write(message.Text);
            // assistantContent += message.Text;
            yield return message.Text;
        }
        yield return assistantContent;
    }

    public Task<SampleDto> GetAsync()
    {
        return Task.FromResult(
            new SampleDto
            {
                Value = 42
            }
        );
    }

    [Authorize]
    public Task<SampleDto> GetAuthorizedAsync()
    {
        return Task.FromResult(
            new SampleDto
            {
                Value = 42
            }
        );
    }
}


public class Tools
{
    [Description("读取文件，返回文件内容")]
  public  static string read_from_file([Description("文件路径")] string path)
    {
        if (!Path.Exists(path))
        {
            return $"文件{path}不存在";
        }
        return File.ReadAllText(path, Encoding.UTF8);
    }
    [Description("写入文件内容，如果成功返回true，否则返回false")]
   public static bool write_to_file([Description("文件路径")] string path, [Description("文件内容")] string content)
    {
        try
        {
            if (!Directory.Exists(Path.GetDirectoryName(path)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(path));
            }
            File.WriteAllText(path, content, Encoding.UTF8);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
    [Description("编辑文件，如果成功返回true，否则返回false")]
   public static bool replace_in_file([Description("文件路径")] string path, [Description("修改文件的内容")] List<replace_in_file_item> items)
    {
        try
        {
            // 读取文件所有行
            string[] lines = File.ReadAllLines(path, Encoding.UTF8);

            // 对每个编辑项进行处理
            foreach (var item in items)
            {
                // 确保行号在有效范围内
                if (item.LineNumber >= 0 && item.LineNumber < lines.Length)
                {
                    // 替换指定行的内容
                    lines[item.LineNumber] = item.NewContent;
                }
                else
                {
                    // 行号无效，返回false
                    return false;
                }
            }

            // 将修改后的内容写回文件
            File.WriteAllLines(path, lines, Encoding.UTF8);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
    [Description("删除文件，如果成功返回true，否则返回false")]
  public  static bool delete_file([Description("文件路径")] string path)
    {
        File.Delete(path);
        return true;
    }
    [Description("列出文件，可以根据文件名或扩展名过滤")]
    public static List<string> list_file([Description("文件夹路径")] string path,[Description("文件名过滤")]string pattern="*")
    {
        List<string> list = new List<string>();

        foreach (string file in Directory.GetFiles(path, pattern))
        {
            list.Add(file);
        }
        foreach (string dir in Directory.GetDirectories(path))
        {
            if (dir == "bin" || dir == "obj" || dir == "node_modules")
            {
                continue;
            }
            list.AddRange(list_file(dir, pattern));
        }
        return list;
    }
    [Description("执行命令行，返回命令行输出")]
    public static async Task<string> execute_command([Description("命令")]string command,
        [Description("命令参数")]string arguments = "",
        [Description("执行目录")]string workingDirectory = null)
    {
        var processInfo = new ProcessStartInfo
        {
            FileName = command,
            Arguments = arguments,
            UseShellExecute = false, // 必须为 false 才能重定向输出
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        };

        if (!string.IsNullOrEmpty(workingDirectory))
        {
            processInfo.WorkingDirectory = workingDirectory;
        }

        using (var process = new Process { StartInfo = processInfo })
        {
            // 异步读取输出和错误流，避免死锁
            var outputTask = process.StandardOutput.ReadToEndAsync();
            var errorTask = process.StandardError.ReadToEndAsync();

            process.Start();

            // 等待进程退出和读取完成
            await Task.WhenAll(
                Task.Run(() => process.WaitForExit()),
                outputTask,
                errorTask);

            return outputTask.Result+ errorTask.Result;
        }
    }

}

    public class replace_in_file_item
    {
        /// <summary>
        /// 要修改的行号（0-based）
        /// </summary>
        public int LineNumber { get; set; }
        /// <summary>
        /// 新的行内容
        /// </summary>
        public string NewContent { get; set; }
    }
